package fuzion24.device.vulnerability.vulnerabilities.framework.zip;

import android.content.Context;

import org.apache.commons.compress.archivers.zip.ModdedZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ModdedZipArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import fuzion24.device.vulnerability.util.CPUArch;
import fuzion24.device.vulnerability.vulnerabilities.VulnerabilityTest;

public class ZipBug9695860 implements VulnerabilityTest {
    /*

     */
    @Override
    public String getCVEorID() {
        return "ZipBug 9695860";
    }



    @Override
    public List<CPUArch> getSupportedArchitectures() {
        ArrayList<CPUArch> archs = new ArrayList<>();
        archs.add(CPUArch.ALL);
        return archs;
    }

    private long getCRC(byte[]data){
        CRC32 crc = new CRC32();
        crc.reset();
        crc.update(data);
        return crc.getValue();
    }

    @Override
    public boolean isVulnerable(Context context) throws Exception {
        String fileName1 = "test_file_name1";
        String fileName2 = "test_file_name2";

        byte []file1Data = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".getBytes();
        byte []file2data = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB".getBytes();

        // create the template data
        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
        ModdedZipArchiveOutputStream out = new ModdedZipArchiveOutputStream(bytesOut);

        ModdedZipArchiveEntry ze1 = new ModdedZipArchiveEntry(fileName1);
        ze1.setCrc(getCRC(file1Data));
        ze1.setSize(file1Data.length);
        ze1.setMethod(ZipEntry.STORED);

        ModdedZipArchiveEntry ze2 = new ModdedZipArchiveEntry(fileName2);
        ze2.setCrc(getCRC(file2data));
        ze2.setSize(file2data.length);
        ze2.setMethod(ZipEntry.STORED);

        out.putArchiveEntry(ze1);
        out.write(file1Data);
        out.closeArchiveEntry();

        out.putArchiveEntry(ze2);
        out.write(file2data);
        out.closeArchiveEntry();

        List<ZipArchiveEntry> normalEntries = new ArrayList<>();
        List<ZipArchiveEntry> moddedEntries = new ArrayList<>();
        normalEntries.add(ze1);
        moddedEntries.add(ze2);

        out.flush();
        out.finish(normalEntries, moddedEntries);

        // write the result to a file
        File outputDir = context.getCacheDir();
        File badZip = File.createTempFile("prefix", "extension", outputDir);
        badZip.deleteOnExit();
        FileOutputStream outstream = new FileOutputStream(badZip);
        outstream.write(bytesOut.toByteArray());
        outstream.close();

        // see if we can still handle it
        ZipFile bad = new ZipFile(badZip);
        final Enumeration<? extends ZipEntry> entries = bad.entries();
        while ( entries.hasMoreElements() )
        {
            final ZipEntry entry = entries.nextElement();
            if(entry.getName().equals(fileName2))
                return true;
        }
        bad.close();
        return false;

    }
}
